<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF在线签章</title>
    <style>
        body {
            font-family: 'Microsoft YaHei', sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
        }
        .toolbar {
            display: flex;
            justify-content: space-between;
            margin-bottom: 20px;
            padding: 15px;
            background-color: #f0f0f0;
            border-radius: 5px;
        }
        .btn {
            padding: 8px 15px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s;
            margin-right: 8px;
        }
        .btn:hover {
            background-color: #45a049;
        }
        .btn-upload {
            background-color: #2196F3;
        }
        .btn-upload:hover {
            background-color: #0b7dda;
        }
        .btn-reset {
            background-color: #f44336;
        }
        .btn-reset:hover {
            background-color: #d32f2f;
        }
        .btn-preview {
            background-color: #9c27b0;
        }
        .btn-preview:hover {
            background-color: #7b1fa2;
        }
        .stamp-panel {
            display: flex;
            margin-bottom: 20px;
        }
        .stamp-list {
            width: 200px;
            padding: 10px;
            background-color: #f9f9f9;
            border-radius: 5px;
            margin-right: 20px;
            overflow-y: auto;
            max-height: 600px;
        }
        .stamp-item {
            margin-bottom: 10px;
            cursor: pointer;
            padding: 8px;
            border-radius: 4px;
            transition: all 0.3s;
            position: relative;
        }
        .stamp-item:hover {
            background-color: #e0e0e0;
        }
        .stamp-item.active {
            background-color: #d4edda;
            border: 1px solid #c3e6cb;
        }
        .stamp-item img {
            max-width: 100%;
            height: auto;
            display: block;
            object-fit: contain;
        }
        .stamp-item-delete {
            position: absolute;
            top: 0;
            right: 0;
            background-color: #f44336;
            color: white;
            border: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            cursor: pointer;
            display: none;
        }
        .stamp-item:hover .stamp-item-delete {
            display: block;
        }
        .pdf-container {
            position: relative;
            border: 1px solid #ddd;
            overflow: auto;
            height: 600px;
            background-color: #eee;
            flex-grow: 1;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .pdf-viewer {
            position: relative;
            margin: auto;
            box-shadow: 0 0 5px rgba(0,0,0,0.2);
        }
        .pdf-canvas {
            display: block;
            margin: 0 auto;
        }
        .stamp-preview {
            position: absolute;
            cursor: move;
            z-index: 100;
            user-select: none;
            transform-origin: center center;
        }
        .stamp-preview img {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }
        .stamp-controls {
            position: absolute;
            top: -30px;
            left: 0;
            display: none;
            z-index: 101;
            background-color: rgba(0,0,0,0.7);
            border-radius: 15px;
            padding: 3px;
        }
        .stamp-preview:hover .stamp-controls {
            display: flex;
        }
        .stamp-control-btn {
            background-color: #333;
            color: white;
            border: none;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            margin-right: 3px;
            cursor: pointer;
            font-size: 12px;
            line-height: 24px;
            text-align: center;
            transition: background-color 0.3s;
        }
        .stamp-control-btn:hover {
            background-color: #555;
        }
        .stamp-control-btn.rotate-left {
            background-color: #2196F3;
        }
        .stamp-control-btn.rotate-right {
            background-color: #2196F3;
        }
        .stamp-control-btn.zoom-in {
            background-color: #4CAF50;
        }
        .stamp-control-btn.zoom-out {
            background-color: #f44336;
        }
        .upload-area {
            border: 2px dashed #ccc;
            padding: 20px;
            text-align: center;
            margin-bottom: 20px;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s;
        }
        .upload-area:hover {
            border-color: #999;
            background-color: #f5f5f5;
        }
        .upload-area.active {
            border-color: #4CAF50;
            background-color: #f0fff0;
        }
        .hidden {
            display: none;
        }
        .loading {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            display: none;
        }
        .spinner {
            border: 5px solid #f3f3f3;
            border-top: 5px solid #3498db;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        .page-nav {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 15px;
        }
        .page-info {
            margin: 0 15px;
            font-weight: bold;
        }
        .page-btn {
            padding: 5px 10px;
            background-color: #e0e0e0;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        .page-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        .alert {
            padding: 15px;
            margin-bottom: 20px;
            border-radius: 4px;
            display: none;
        }
        .alert-error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
        .alert-success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .preview-mode {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.9);
            z-index: 2000;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            display: none;
        }
        .preview-container {
            max-width: 90%;
            max-height: 90%;
            overflow: auto;
            background-color: white;
            padding: 20px;
            border-radius: 5px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .preview-toolbar {
            margin-bottom: 15px;
            display: flex;
            justify-content: flex-end;
            width: 90%;
        }
        .preview-canvas {
            max-width: 100%;
            max-height: calc(100vh - 100px);
            object-fit: contain;
        }
        .stamp-size-control {
            position: absolute;
            bottom: -5px;
            right: -5px;
            width: 10px;
            height: 10px;
            background-color: #2196F3;
            cursor: nwse-resize;
            z-index: 102;
            display: none;
        }
        .stamp-preview:hover .stamp-size-control {
            display: block;
        }
        .upload-stamp-title {
            font-weight: bold;
            margin-bottom: 10px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="alert alert-error" id="error-alert"></div>
        <div class="alert alert-success" id="success-alert"></div>
        <div class="toolbar">
            <div>
                <input type="file" id="pdf-upload" accept=".pdf" class="hidden">
                <button class="btn btn-upload" id="upload-pdf-btn">选择 PDF</button>
                <button class="btn" id="add-stamp-btn">添加签章</button>
                <button class="btn btn-reset" id="reset-btn">重置</button>
            </div>
            <div>
                <button class="btn btn-preview" id="preview-btn">预览</button>
            </div>
        </div>
        
        <div class="page-nav" id="page-nav" style="display: none;">
            <button class="page-btn" id="prev-page-btn" disabled>上一页</button>
            <span class="page-info" id="page-info">第 1 页 / 共 1 页</span>
            <button class="page-btn" id="next-page-btn" disabled>下一页</button>
        </div>
        
        <div class="stamp-panel">
            <div class="stamp-list" id="stamp-list">
                <div class="upload-stamp-title">选择签章 (PNG/JPG)</div>
                <div id="stamp-items-container"></div>
                <div class="upload-area" id="stamp-upload-area">
                    <p>点击或拖拽选择签章图片</p>
                    <input type="file" id="stamp-upload" accept="image/png,image/jpeg" class="hidden" multiple>
                </div>
            </div>
            
            <div class="pdf-container" id="pdf-container">
                <div id="pdf-viewer"></div>
            </div>
        </div>
    </div>
    
    <div class="loading hidden" id="loading">
        <div class="spinner"></div>
        <div style="color: white; margin-top: 15px;" id="loading-text">正在加载 PDF...</div>
    </div>
    
    <div class="preview-mode" id="preview-mode">
        <div class="preview-toolbar">
            <button class="btn btn-reset" id="close-preview-btn">关闭预览</button>
        </div>
        <div class="preview-container">
            <canvas id="preview-canvas" class="preview-canvas"></canvas>
        </div>
    </div>
    
    <script src="../js/pdf.min.js"></script>
    <script>
        // 设置PDF.js worker路径
        pdfjsLib.GlobalWorkerOptions.workerSrc = '../js/pdf.worker.min.js';
        
        // 全局变量
        const pdfUpload = document.getElementById('pdf-upload');
        const uploadPdfBtn = document.getElementById('upload-pdf-btn');
        const addStampBtn = document.getElementById('add-stamp-btn');
        const resetBtn = document.getElementById('reset-btn');
        const previewBtn = document.getElementById('preview-btn');
        const closePreviewBtn = document.getElementById('close-preview-btn');
        const stampList = document.getElementById('stamp-list');
        const stampUploadArea = document.getElementById('stamp-upload-area');
        const stampUpload = document.getElementById('stamp-upload');
        const stampItemsContainer = document.getElementById('stamp-items-container');
        const pdfContainer = document.getElementById('pdf-container');
        const pdfViewer = document.getElementById('pdf-viewer');
        const loading = document.getElementById('loading');
        const loadingText = document.getElementById('loading-text');
        const errorAlert = document.getElementById('error-alert');
        const successAlert = document.getElementById('success-alert');
        const pageNav = document.getElementById('page-nav');
        const prevPageBtn = document.getElementById('prev-page-btn');
        const nextPageBtn = document.getElementById('next-page-btn');
        const pageInfo = document.getElementById('page-info');
        const previewMode = document.getElementById('preview-mode');
        const previewCanvas = document.getElementById('preview-canvas');

        let pdfDoc = null;
        let currentPage = 1;
        let selectedStamp = null;
        let stamps = [];
        let stampImages = [];
        let scale = 1.0;
        let pdfCanvas = null;


        // 初始化事件监听
        function initEventListeners() {
            uploadPdfBtn.addEventListener('click', () => {
                pdfUpload.click();
            });

            pdfUpload.addEventListener('change', handlePdfUpload);

            addStampBtn.addEventListener('click', addStampToPdf);

            resetBtn.addEventListener('click', resetSystem);

            previewBtn.addEventListener('click', previewSignedPdf);

            closePreviewBtn.addEventListener('click', () => {
                previewMode.style.display = 'none';
            });

            prevPageBtn.addEventListener('click', () => {
                if (currentPage > 1) {
                    currentPage--;
                    renderPage(currentPage);
                    updatePageNav();
                }
            });

            nextPageBtn.addEventListener('click', () => {
                if (currentPage < pdfDoc.numPages) {
                    currentPage++;
                    renderPage(currentPage);
                    updatePageNav();
                }
            });

            stampUploadArea.addEventListener('click', () => {
                stampUpload.click();
            });

            stampUploadArea.addEventListener('dragover', (e) => {
                e.preventDefault();
                stampUploadArea.classList.add('active');
            });

            stampUploadArea.addEventListener('dragleave', () => {
                stampUploadArea.classList.remove('active');
            });

            stampUploadArea.addEventListener('drop', (e) => {
                e.preventDefault();
                stampUploadArea.classList.remove('active');
                const files = e.dataTransfer.files;
                if (files.length > 0) {
                    handleStampUpload(files);
                }
            });

            stampUpload.addEventListener('change', (e) => {
                const files = e.target.files;
                if (files.length > 0) {
                    handleStampUpload(files);
                }
            });
        }

        // 处理PDF选择
        async function handlePdfUpload(e) {
            const file = e.target.files[0];
            if (!file) return;

            if (file.size > 10 * 1024 * 1024) {
                showError('文件大小不能超过10MB');
                return;
            }

            try {
                showLoading('正在加载 PDF...');
                const fileReader = new FileReader();
                
                fileReader.onload = async (event) => {
                    try {
                        const typedArray = new Uint8Array(event.target.result);
                        pdfDoc = await pdfjsLib.getDocument({ data: typedArray }).promise;
                        
                        // 清除之前的签章
                        stamps.forEach(stamp => stamp.remove());
                        stamps = [];
                        
                        renderPage(currentPage);
                        updatePageNav();
                        hideLoading();
                        showSuccess('PDF加载成功');
                    } catch (err) {
                        console.error('PDF加载错误:', err);
                        showError('PDF加载失败，请检查文件格式');
                        hideLoading();
                    }
                };
                
                fileReader.onerror = () => {
                    showError('文件读取失败');
                    hideLoading();
                };
                
                fileReader.readAsArrayBuffer(file);
            } catch (err) {
                console.error('选择错误:', err);
                showError('选择失败');
                hideLoading();
            }
        }

        // 渲染PDF页面
        async function renderPage(pageNum) {
            if (!pdfDoc) return;
            
            try {
                showLoading('正在渲染页面...');
                
                const page = await pdfDoc.getPage(pageNum);
                const viewport = page.getViewport({ scale: scale });
                
                // 创建Canvas
                pdfCanvas = document.createElement('canvas');
                const context = pdfCanvas.getContext('2d');
                pdfCanvas.width = viewport.width;
                pdfCanvas.height = viewport.height;
                pdfCanvas.classList.add('pdf-canvas');
                
                // 清空并添加Canvas
                pdfViewer.innerHTML = '';
                pdfViewer.appendChild(pdfCanvas);
                
                // 渲染PDF页面
                await page.render({
                    canvasContext: context,
                    viewport: viewport
                }).promise;
                
                // 重新添加当前页的签章
                const pageStamps = stamps.filter(stamp => stamp.dataset.page == pageNum);
                pageStamps.forEach(stamp => {
                    pdfViewer.appendChild(stamp);
                });
                
                hideLoading();
            } catch (err) {
                console.error('页面渲染错误:', err);
                showError('页面渲染失败');
                hideLoading();
            }
        }

        // 更新分页导航
        function updatePageNav() {
            if (!pdfDoc) {
                pageNav.style.display = 'none';
                return;
            }
            
            pageNav.style.display = 'flex';
            pageInfo.textContent = `第 ${currentPage} 页 / 共 ${pdfDoc.numPages} 页`;
            prevPageBtn.disabled = currentPage <= 1;
            nextPageBtn.disabled = currentPage >= pdfDoc.numPages;
        }

        // 处理签章选择
        function handleStampUpload(files) {
            if (files.length === 0) return;
            
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                if (!file.type.match('image.*')) {
                    showError('请选择图片文件 (PNG/JPG)');
                    continue;
                }
                
                const reader = new FileReader();
                reader.onload = (event) => {
                    const stampUrl = event.target.result;
                    addStampToLibrary(stampUrl);
                };
                reader.readAsDataURL(file);
            }
            
            showSuccess('签章选择成功');
        }

        // 添加签章到库
        function addStampToLibrary(stampUrl) {
            const stampItem = document.createElement('div');
            stampItem.classList.add('stamp-item');
            
            const stampImg = new Image();
            stampImg.src = stampUrl;
            stampImg.style.maxHeight = '100px';
            
            const deleteBtn = document.createElement('button');
            deleteBtn.classList.add('stamp-item-delete');
            deleteBtn.innerHTML = '&times;';
            deleteBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                stampItem.remove();
                stampImages = stampImages.filter(img => img !== stampUrl);
                if (selectedStamp === stampUrl) {
                    selectedStamp = stampImages.length > 0 ? stampImages[0] : null;
                    if (selectedStamp) {
                        stampItemsContainer.querySelector('.stamp-item').classList.add('active');
                    }
                }
            });
            
            stampItem.appendChild(stampImg);
            stampItem.appendChild(deleteBtn);
            
            stampItem.addEventListener('click', () => {
                const activeStamp = stampList.querySelector('.stamp-item.active');
                if (activeStamp) {
                    activeStamp.classList.remove('active');
                }
                stampItem.classList.add('active');
                selectedStamp = stampUrl;
            });
            
            stampItemsContainer.appendChild(stampItem);
            stampImages.push(stampUrl);
            
            // 如果是第一个签章，自动选中
            if (stampImages.length === 1) {
                stampItem.classList.add('active');
                selectedStamp = stampUrl;
            }
        }

        // 添加签章到PDF
        function addStampToPdf() {
            if (!selectedStamp) {
                showError('请先选择签章');
                return;
            }
            
            if (!pdfDoc) {
                showError('请先选择PDF文件');
                return;
            }
            
            if (!pdfCanvas) {
                showError('请等待PDF加载完成');
                return;
            }
            
            const stampImg = new Image();
            stampImg.src = selectedStamp;
            
            const stampPreview = document.createElement('div');
            stampPreview.classList.add('stamp-preview');
            stampPreview.dataset.page = currentPage;
            stampPreview.appendChild(stampImg);
            
            // 设置初始位置为PDF中心
            const viewerRect = pdfViewer.getBoundingClientRect();
            const stampWidth = 100;
            const stampHeight = 100;
            const left = (viewerRect.width - stampWidth) / 2;
            const top = (viewerRect.height - stampHeight) / 2;
            
            stampPreview.style.position = 'absolute';
            stampPreview.style.left = `${left}px`;
            stampPreview.style.top = `${top}px`;
            stampPreview.style.width = `${stampWidth}px`;
            stampPreview.style.height = `${stampHeight}px`;
            
            // 添加控制按钮
            const controls = document.createElement('div');
            controls.classList.add('stamp-controls');
            
            const rotateLeftBtn = createControlButton('↺', 'rotate-left');
            rotateLeftBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                rotateStamp(stampPreview, -15);
            });
            
            const rotateRightBtn = createControlButton('↻', 'rotate-right');
            rotateRightBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                rotateStamp(stampPreview, 15);
            });
            
            const zoomInBtn = createControlButton('+', 'zoom-in');
            zoomInBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                resizeStamp(stampPreview, 1.1);
            });
            
            const zoomOutBtn = createControlButton('-', 'zoom-out');
            zoomOutBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                resizeStamp(stampPreview, 0.9);
            });
            
            const removeBtn = createControlButton('×', 'remove');
            removeBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                stampPreview.remove();
                stamps = stamps.filter(stamp => stamp !== stampPreview);
            });
            
            controls.appendChild(rotateLeftBtn);
            controls.appendChild(rotateRightBtn);
            controls.appendChild(zoomInBtn);
            controls.appendChild(zoomOutBtn);
            controls.appendChild(removeBtn);
            stampPreview.appendChild(controls);
            
            // 添加大小调整控制点
            const sizeControl = document.createElement('div');
            sizeControl.classList.add('stamp-size-control');
            stampPreview.appendChild(sizeControl);
            
            // 使签章可拖动
            makeDraggable(stampPreview, sizeControl);
            
            pdfViewer.appendChild(stampPreview);
            stamps.push(stampPreview);
        }

        // 创建控制按钮
        function createControlButton(text, className) {
            const btn = document.createElement('button');
            btn.classList.add('stamp-control-btn');
            if (className) btn.classList.add(className);
            btn.textContent = text;
            return btn;
        }

        // 旋转签章
        function rotateStamp(stamp, degrees) {
            const currentRotation = stamp.dataset.rotation ? parseInt(stamp.dataset.rotation) : 0;
            const newRotation = (currentRotation + degrees) % 360;
            stamp.style.transform = `rotate(${newRotation}deg)`;
            stamp.dataset.rotation = newRotation;
        }

        // 调整签章大小
        function resizeStamp(stamp, factor) {
            const currentWidth = parseFloat(stamp.style.width) || 100;
            const currentHeight = parseFloat(stamp.style.height) || 100;
            
            // 保持宽高比
            const img = stamp.querySelector('img');
            const aspectRatio = img.naturalWidth / img.naturalHeight;
            
            let newWidth, newHeight;
            
            if (aspectRatio > 1) {
                // 宽图
                newWidth = currentWidth * factor;
                newHeight = newWidth / aspectRatio;
            } else {
                // 高图或方图
                newHeight = currentHeight * factor;
                newWidth = newHeight * aspectRatio;
            }
            
            // 限制最小和最大尺寸
            if (newWidth < 30 || newHeight < 30) return;
            if (newWidth > 300 || newHeight > 300) return;
            
            stamp.style.width = `${newWidth}px`;
            stamp.style.height = `${newHeight}px`;
        }

        // 使元素可拖动 - 完全自由拖动版本
function makeDraggable(element, resizeHandle = null) {
    let isDragging = false;
    let isResizing = false;
    let startX, startY, startLeft, startTop;
    let startWidth, startHeight;

    // 拖动处理
    element.addEventListener('mousedown', (e) => {
        if (e.target === resizeHandle) {
            // 大小调整处理
            isResizing = true;
            startX = e.clientX;
            startY = e.clientY;
            startWidth = parseFloat(element.style.width) || 100;
            startHeight = parseFloat(element.style.height) || 100;
            e.preventDefault();
            e.stopPropagation();
        } else {
            // 拖动处理
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            startLeft = parseFloat(element.style.left) || 0;
            startTop = parseFloat(element.style.top) || 0;
            element.style.zIndex = '200'; // 拖动时置于顶层
            e.preventDefault();
        }
    });

    document.addEventListener('mousemove', (e) => {
        if (!isDragging && !isResizing) return;
        
        if (isDragging) {
            // 计算移动距离
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            
            // 计算新位置 - 完全自由，不限制边界
            const newLeft = startLeft + dx;
            const newTop = startTop + dy;
            
            // 应用新位置
            element.style.left = `${newLeft}px`;
            element.style.top = `${newTop}px`;
        } else if (isResizing) {
            // 大小调整逻辑保持不变
            const deltaX = e.clientX - startX;
            const deltaY = e.clientY - startY;
            
            const img = element.querySelector('img');
            const aspectRatio = img.naturalWidth / img.naturalHeight;
            
            let newWidth, newHeight;
            
            if (aspectRatio > 1) {
                // 宽图
                newWidth = startWidth + deltaX;
                newHeight = newWidth / aspectRatio;
            } else {
                // 高图或方图
                newHeight = startHeight + deltaY;
                newWidth = newHeight * aspectRatio;
            }
            
            // 限制最小和最大尺寸
            if (newWidth >= 30 && newWidth <= 300 && newHeight >= 30 && newHeight <= 300) {
                element.style.width = `${newWidth}px`;
                element.style.height = `${newHeight}px`;
            }
        }
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        isResizing = false;
        element.style.zIndex = '100';
    });
}
        // 重置系统
        function resetSystem() {
            pdfViewer.innerHTML = '';
            stamps.forEach(stamp => stamp.remove());
            stamps = [];
            currentPage = 1;
            pdfDoc = null;
            pdfUpload.value = '';
            updatePageNav();
            showSuccess('系统已重置');
        }

        // 预览签章后的PDF
        async function previewSignedPdf() {
            if (!pdfDoc) {
                showError('请先选择PDF文件');
                return;
            }
            
            if (stamps.length === 0) {
                showError('请先添加签章');
                return;
            }
            
            try {
                showLoading('正在生成预览...');
                
                // 获取原始PDF数据
                const pdfBytes = await pdfDoc.getData();
                const modifiedPdf = await pdfjsLib.getDocument({ data: pdfBytes }).promise;
                const page = await modifiedPdf.getPage(currentPage);
                const viewport = page.getViewport({ scale: 1.0 });
                
                // 设置预览Canvas大小
                previewCanvas.width = viewport.width;
                previewCanvas.height = viewport.height;
                const context = previewCanvas.getContext('2d');
                
                // 渲染原始PDF页面
                await page.render({
                    canvasContext: context,
                    viewport: viewport
                }).promise;
                
                // 绘制所有签章
                const pageStamps = stamps.filter(stamp => stamp.dataset.page == currentPage);
                for (const stamp of pageStamps) {
                    const stampImg = stamp.querySelector('img');
                    const rect = stamp.getBoundingClientRect();
                    const pdfRect = pdfCanvas.getBoundingClientRect();
                    
                    const x = rect.left - pdfRect.left;
                    const y = rect.top - pdfRect.top;
                    const width = rect.width;
                    const height = rect.height;
                    
                    // 应用旋转
                    if (stamp.dataset.rotation) {
                        const rotation = parseInt(stamp.dataset.rotation);
                        if (rotation !== 0) {
                            context.save();
                            context.translate(x + width/2, y + height/2);
                            context.rotate(rotation * Math.PI / 180);
                            context.drawImage(stampImg, -width/2, -height/2, width, height);
                            context.restore();
                            continue;
                        }
                    }
                    
                    // 保持签章图片比例
                    const imgAspectRatio = stampImg.naturalWidth / stampImg.naturalHeight;
                    let drawWidth = width;
                    let drawHeight = height;
                    
                    if (width/height > imgAspectRatio) {
                        drawWidth = height * imgAspectRatio;
                    } else {
                        drawHeight = width / imgAspectRatio;
                    }
                    
                    context.drawImage(stampImg, x + (width - drawWidth)/2, y + (height - drawHeight)/2, drawWidth, drawHeight);
                }
                
                previewMode.style.display = 'flex';
                hideLoading();
            } catch (err) {
                console.error('预览生成错误:', err);
                showError('预览生成失败');
                hideLoading();
            }
        }

        // 显示加载指示器
        function showLoading(text = '正在处理...') {
            loading.style.display = 'flex';
            loadingText.textContent = text;
        }

        // 隐藏加载指示器
        function hideLoading() {
            loading.style.display = 'none';
        }

        // 显示错误消息
        function showError(message) {
            errorAlert.textContent = message;
            errorAlert.style.display = 'block';
            setTimeout(() => {
                errorAlert.style.display = 'none';
            }, 5000);
        }

        // 显示成功消息
        function showSuccess(message) {
            successAlert.textContent = message;
            successAlert.style.display = 'block';
            setTimeout(() => {
                successAlert.style.display = 'none';
            }, 3000);
        }

        // 初始化应用
        function initApp() {
            initEventListeners();
        }

        // 启动应用
        initApp();
    </script>
</body>
</html>